package com.ubxtech.gateway.util;

import com.alibaba.fastjson2.JSONObject;
import com.ubxtech.core.context.Result;
import com.ubxtech.core.exception.ErrorCode;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.nio.CharBuffer;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.atomic.AtomicReference;

/**
 * @author Victor.Xiao
 * @since 2023-08-18 18:14
 **/
public class ResponseUtil {
    public static Mono<Void> write(ServerHttpResponse response, ErrorCode errorCode) {
        HttpHeaders httpHeaders = response.getHeaders();
        //ReadOnlyHttpHeaders修改会报错
        if (!httpHeaders.getClass().toString().contains("ReadOnlyHttpHeaders")) {
            // 响应类型
            response.getHeaders().add("Content-Type", MediaType.APPLICATION_JSON_VALUE);
        }
        // 响应状态码
        response.setStatusCode(resolveCode(errorCode.getCode()));
        // 响应内容
        // 可以自定义全局返回类
        String message = JSONObject.toJSONString(new Result<>(errorCode));
        DataBuffer buffer = response.bufferFactory().wrap(message.getBytes());

        return response.writeWith(Mono.just(buffer));
    }


    public static Mono<Void> write(ServerHttpResponse response, int code ,String msg) {
        HttpHeaders httpHeaders = response.getHeaders();
        //ReadOnlyHttpHeaders修改会报错
        if (!httpHeaders.getClass().toString().contains("ReadOnlyHttpHeaders")) {
            // 响应类型
            response.getHeaders().add("Content-Type", MediaType.APPLICATION_JSON_VALUE);
        }
        // 响应状态码
        response.setStatusCode(resolveCode(code));
        // 响应内容
        // 可以自定义全局返回类
        String message = JSONObject.toJSONString(new Result<>(code,msg));
        DataBuffer buffer = response.bufferFactory().wrap(message.getBytes());

        return response.writeWith(Mono.just(buffer));
    }

    public static Mono<Void> write(ServerHttpResponse response, HttpStatus httpStatus,String msg) {
        // 响应类型
        response.getHeaders().add("Content-Type", MediaType.APPLICATION_JSON_VALUE);
        // 响应状态码
        response.setStatusCode(httpStatus);
        // 响应内容
        // 可以自定义全局返回类
        String message = JSONObject.toJSONString(new Result<>(httpStatus.value(),msg));
        DataBuffer buffer = response.bufferFactory().wrap(message.getBytes());

        return response.writeWith(Mono.just(buffer));
    }


    public static HttpStatus resolveCode(Integer code) {
        if (code >= 600) {
            return HttpStatus.INTERNAL_SERVER_ERROR;
        }
        for (HttpStatus value : HttpStatus.values()) {
            if (value.value() == code) {
                return value;
            }
        }
        return HttpStatus.INTERNAL_SERVER_ERROR;
    }


    /**
     * 从Flux<DataBuffer>中获取字符串的方法
     * @author Victor.Xiao
     * @since 2023-08-23 15:39
     * @param serverHttpRequest serverHttpRequest
     * @return java.lang.String
    */
    public static String getRequestBody(ServerHttpRequest serverHttpRequest) {
        //获取请求体
        Flux<DataBuffer> body = serverHttpRequest.getBody();
        AtomicReference<String> bodyReference = new AtomicReference<>();
        body.subscribe(buffer -> {
            CharBuffer charBuffer = StandardCharsets.UTF_8.decode(buffer.asByteBuffer());
            DataBufferUtils.release(buffer);
            bodyReference.set(charBuffer.toString());
        });
        //获取request body
        return bodyReference.get();
    }

    /**
     * 判断是不是json body请求
     * @author Victor.Xiao
     * @since 2023-08-23 15:42
     * @param mediaType mediaType
     * @return boolean
    */
    public static boolean isJsonMediaType(MediaType mediaType) {
        if (mediaType == null) {
            return false;
        }
        return MediaType.APPLICATION_FORM_URLENCODED.isCompatibleWith(mediaType) || MediaType.APPLICATION_JSON.isCompatibleWith(mediaType);
    }

}
